package callgraph;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import org.apache.bcel.Repository;
import org.apache.bcel.classfile.JavaClass;
import org.apache.bcel.classfile.Method;
import org.apache.bcel.generic.ConstantPoolGen;
import org.apache.bcel.generic.InstructionHandle;
import org.apache.bcel.generic.InstructionList;
import org.apache.bcel.generic.MethodGen;

public class CG {

	/***
	 *TODO show message to indicate that need to increase the size of the array if more than 500 methods
	 *TODO use a sparse representation if memory becomes a problem
	 */
	AdjacencyMatrix matrix = new AdjacencyMatrix(500);
	
	private void cgForOneClass(String name) throws ClassNotFoundException {
		JavaClass clazz   = Repository.lookupClass(name);
		String cname = clazz.getClassName();
		ConstantPoolGen cpg = new ConstantPoolGen(clazz.getConstantPool());
		Method[] methods = clazz.getMethods();
		for(int i=0; i < methods.length; i++) {
			MethodGen mg  = new MethodGen(methods[i], cname, cpg);
			if (mg.getName().equals("main")) continue;
			InstructionList ilist = mg.getInstructionList();
			List mcalls = new ArrayList();
			CollectMethodCallsVisitor vis = new CollectMethodCallsVisitor(mcalls,cpg);
			Iterator it = ilist.iterator(); 
			while (it.hasNext()) {
				InstructionHandle handle =  (InstructionHandle) it.next();
				handle.accept(vis);
			}
			matrix.update(mg.getClassName()+"."+mg.getName()+mg.getSignature(), mcalls);
		}
	}
	
	public static void main(String[] argv) throws ClassNotFoundException {
		CG cg = new CG();
		if (argv!=null & argv.length != 0) {
			for (String name : argv) {
//				String name = /*argv[0]*/ "bcelutil.sample.QuickSort";
				cg.cgForOneClass(name);
			}
		}
		System.out.println(cg.matrix.toString());
	}
	
}